#pragma once
#ifndef OBR_MESH_H
#define OBR_MESH_H

#include "ASNode.h"
#include "Configurable.h"
#include "Material.h"
#include "SharedDS/MeshData.h"
#include "VirtualProgramEntry.h"
#include "common.h"
#include "helpers/Helpers.h"

namespace OBR
{

/**
 * @brief base class of all meshes
 *
 */
class Mesh : public ASNode, public VirtualProgramEntry
{
public:
    /* --------------------------- static members --------------------------- */
    static size_t gas_total_built_sbt; // this is set when GAS is built

    /* ------------------------- non-static members ------------------------- */
    int gas_sbt_base = -1; // this is set when GAS is built
    CudaBuffer d_gas_output;

private:
    /**
     * @brief get GAS build input
     *
     * @return OptixBuildInput
     */
    virtual OptixBuildInput getASBuildInput() = 0;

    /**
     * @brief get GAS build options
     *
     * @return OptixAccelBuildOptions
     */
    virtual OptixAccelBuildOptions getASBuildOptions() = 0;

    void buildAccelStructure(OptixDeviceContext &ctx, CUstream &stream) override;

public:
    Mesh(std::string cuda_source_path);
    virtual ~Mesh();

    virtual void updateAABB() = 0;

protected:
    uint32_t *build_flags = nullptr;
};

} // namespace OBR

#endif